package com.cci.kangdao.message;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import com.cci.kangdao.utilTool.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.cci.kangdao.dao.GMNotifyRecordDao;
import com.cci.kangdao.dao.NotifyRecordDYDao;
import com.cci.kangdao.dao.ServiceStationDao;
import com.cci.kangdao.dao.UserTDao;
import com.cci.kangdao.dao.WorkOrderPrincipalTDao;
import com.cci.kangdao.dao.model.GMNotifyRecordT;
import com.cci.kangdao.dao.model.NotifyRecord;
import com.cci.kangdao.enums.GMApplyRecordStatus;

@Component
public class MessagePushUtils {

	private Logger log = Logger.getLogger(MessagePushUtils.class);

	@Autowired
	private ServiceStationDao serviceStationDao;

	@Autowired
	private WorkOrderPrincipalTDao workOrderPrincipalTDao;

	@Autowired
	private UserTDao userTDao;

	@Autowired
	private NotifyRecordDYDao notifyRecordDYDao;

	@Autowired
	private GMNotifyRecordDao gMNotifyRecordDao;

	@Value("${ecummins.web.loginUrl}")
	private String loginUrl;




	public void pushMessageByServiceStationIdAndOrderId(Long orderId, Long serviceStationId , int orderStatus, String content) {

		log.info(String.format("orderId:%s serviceStationId:%s orderStatus:%s ",orderId, serviceStationId, orderStatus));
		// 查询出服务站所有站长和信息员的id集合
		List<Long> userIds = serviceStationDao.getServiceStationUserIdList(serviceStationId);
		if (CollectionUtils.isNotEmpty(userIds)) {
			Set<Long> idSet = new HashSet<>();
			idSet.addAll(userIds);
			// 查询出服务工单此状态下对应的负责人id集合
			// 6:待派服务技师 7:待服务技师接单
			// 服务工单状态未被接单时不需要给服务技师推送消息
			if (orderStatus != 6 && orderStatus != 7) {
				// 查询出服务技师的id
				List<Long> opIds = workOrderPrincipalTDao.getUserIdByOrderIdAndOrderStatus(orderId,
						orderStatus);
				if (CollectionUtils.isNotEmpty(opIds)) {
					idSet.addAll(opIds);
				}
			}

			userIds = new ArrayList<>();
			userIds.addAll(idSet);
			List<UserInfo> userInfos = userTDao.getUserPushInfoByUserId(userIds);
			if (CollectionUtils.isNotEmpty(userInfos)) {
				// 生成消息记录
				List<NotifyRecord> recordList = generateNotifyRecord(userInfos, orderId, content, 0);
				// 推送消息
				doPushMessage(recordList, userInfos);

				if (CollectionUtils.isNotEmpty(recordList)) {
					// 保存消息推送记录
					notifyRecordDYDao.insertBatchNotifyRecord(recordList);
				}
			}
		}

	}


	/**
	 * 给指定User进行消息推送
	 * @param orderId
	 * @param content
	 * @param userId
	 */
	public void pushMessageByUserIds(Long orderId, String content, Long... userId) {
		//pushMessageByServiceStationId(orderId, null, content, userId);

		if (ArrayUtils.isNotEmpty(userId)) {
			List<UserInfo> userInfos = userTDao.getUserPushInfoByUserId(Arrays.asList(userId));
			if (CollectionUtils.isNotEmpty(userInfos)) {
				// 生成消息记录
				List<NotifyRecord> recordList = generateNotifyRecord(userInfos, orderId, content, -1);

				/**
				 * 2.10.0ccec异常关闭的服务工单，暂停对用户的消息推送(短信推送和app推送)
				 * 虽然不推送消息，但是还需要生成消息记录
				 */
				// 推送消息
				//doPushMessage(recordList, userInfos);

				// 保存消息推送记录
				notifyRecordDYDao.insertBatchNotifyRecord(recordList);
			}
		}
	}

	/**
	 * 给站长以及信息员或指定User进行消息推送
	 * @param workOrder
	 * @param serviceStationId
	 * @param content
	 * @param userId  推送消息的userId
	 */
	public void pushMessageByServiceStationId(Long orderId, Long serviceStationId, String content, Long... userId) {
		/**
		 * 注释log
		 * 20230808
		 * sxt 处理Privacy Violation
		 */
		//log.info(String.format("orderId:%s serviceStationId:%s userIds:%s", orderId,serviceStationId,Arrays.toString(userId)));

		// 查询出服务站所有站长和信息员的id集合
		List<Long> userIds = null;
		if(!Objects.isNull(serviceStationId)) {
			userIds = serviceStationDao.getServiceStationUserIdList(serviceStationId);
		}
		if (userIds == null) {
			if (ArrayUtils.isNotEmpty(userId)) {
				userIds = new ArrayList<>();
				userIds.addAll(Arrays.asList(userId));
			}
		} else {
			if (ArrayUtils.isNotEmpty(userId)) {
				userIds.addAll(Arrays.asList(userId));
			}
		}

		if (CollectionUtils.isNotEmpty(userIds)) {
			List<UserInfo> userInfos = userTDao.getUserPushInfoByUserId(userIds);
			if (CollectionUtils.isNotEmpty(userInfos)) {
				// 生成消息记录
				List<NotifyRecord> recordList = generateNotifyRecord(userInfos, orderId, content, 0);
				// 推送消息
				doPushMessage(recordList, userInfos);

				if (CollectionUtils.isNotEmpty(recordList)) {
					// 保存消息推送记录
					notifyRecordDYDao.insertBatchNotifyRecord(recordList);
				}
			}
		}
	}






	/**
	 * 推送消息
	 * @param recordList
	 * @param userInfos
	 */
	private void doPushMessage(List<NotifyRecord> recordList, List<UserInfo> userInfos) {
		if (CollectionUtils.isNotEmpty(recordList) && CollectionUtils.isNotEmpty(userInfos)) {
			// key:UserId  value:UserInfo
			Map<Long, UserInfo> userInfoMap = new HashMap<>();
			for (UserInfo userInfo : userInfos) {
				userInfoMap.put(userInfo.getUserId(), userInfo);
			}

			for (NotifyRecord record : recordList) {
				UserInfo userInfo = userInfoMap.get(record.getReceiverId());
				if (!Objects.isNull(userInfo)) {
					switch (record.getSendType()) {
					// 短信推送
					case 1:
						String phone = userInfo.getPhone();
						if (StringUtils.isNotBlank(phone)) {
							String sendStatus = SmsUtils.sendMessage(phone, record.getContent());
							if ("00".equals(sendStatus)) {
								record.setExceptionInfo(String.format("手机号:%s  发送成功", phone));
							} else {
								record.setStatus(0);
								record.setExceptionInfo(String.format("状态码:%s  手机号:%s  发送失败", sendStatus, phone));
							}
						} else {
							record.setStatus(0);
							record.setExceptionInfo("用户手机号为空");
						}
						break;
					// App推送
					case 2:
						String clientId = userInfo.getClientId();
						if (StringUtils.isNotBlank(clientId)) {
							boolean isSucc = NotifyUtil.push2Single(clientId, record.getContent(), record.getContent());
							if (isSucc) {
								record.setExceptionInfo(String.format("ClientId:%s   消息推送成功", clientId));
							} else {
								record.setStatus(0);
								record.setExceptionInfo(String.format("ClientId:%s   消息推送失败", clientId));
							}
						} else {
							record.setStatus(0);
							record.setExceptionInfo("ClientId为空");
						}
						break;
					default:
						record.setStatus(0);
						record.setExceptionInfo("发送类型不支持");
						break;
					}

				} else {
					record.setStatus(0);
					record.setExceptionInfo("用户不存在");
				}
			}
		}
	}

	/**
	 * 生成消息记录列表
	 * @param userInfos
	 * @param orderId
	 * @param content
	 * @return
	 */
	private List<NotifyRecord> generateNotifyRecord(List<UserInfo> userInfos, Long orderId, String content, Integer msgFlag) {
		if (CollectionUtils.isNotEmpty(userInfos)) {
			List<NotifyRecord> list = new ArrayList<>();
			String currentTime = LocalTimeUtil.getRealCurrentTime();
			for (UserInfo userInfo : userInfos) {
				NotifyRecord r1 = doGenerateNotifyRecord(orderId, userInfo.getUserId(), content, 1, currentTime, msgFlag);
				NotifyRecord r2 = doGenerateNotifyRecord(orderId, userInfo.getUserId(), content, 2, currentTime, msgFlag);
				list.add(r1);
				list.add(r2);
			}
			return list;
		}
		return null;
	}

	private NotifyRecord doGenerateNotifyRecord(Long orderId, Long receiverId, String content, Integer sendType, String currentTime, Integer flag) {
		NotifyRecord record = new NotifyRecord();
		record.setFunction(10);
		record.setCategory(5);
		record.setOrderId(orderId);
		record.setReceiverId(receiverId);
		record.setContent(content);
		record.setSendType(sendType);
		record.setSendTime(currentTime);
		// 按照旧数据的默认 1:发送成功  0：发送失败
		record.setStatus(1);
		// 1:未读；0：已读
		record.setIsRead(1);
		record.setFlag(flag);
		record.setCreateTime(currentTime);
		return record;
	}


	private static String AUDITOR_EMSG = "您有一条Guidanz权限申请需要审批，请尽快处理！申请人（姓名：%s；手机号：%s）点击<a href='%s' target='_blank'>此处</a>去处理<br/>";

	private static String AUDITOR_MSG = "您有一条Guidanz权限申请需要审批，请尽快处理！申请人（姓名：%s；手机号：%s）";

	private static String USER_REJECT_MSG = "您的Guidanz权限申请审核未通过，请在申请记录中查看原因。如有问题请联系服务站站长！";

	public void pushMessageToAuditorForGuidanz(GMApplyRecordStatus recordStatus, Long recordId, Long companyId, Long serviceStationId, Long subServiceStationId, Long userId, String contact, String phone) {

		String content = null;
		List<UserInfo> userInfos = null;
		List<GMNotifyRecordT> gmNotifyRecords = null;

		switch (recordStatus) {
		case ADMIN_AUDIT:

			content = String.format(AUDITOR_EMSG, contact, phone,loginUrl);
			// 如果分公司不为空，则给分公司的管理员发送邮件
			if(Objects.nonNull(subServiceStationId)) {
			// 查询出当前分公司的管理员
				userInfos = userTDao.subStationAdministrator(subServiceStationId);
			// 如果分公司为空，则给渠道管理员发送邮件
			}else {
				// 获取渠道管理员的信息
				userInfos = userTDao.getChannelAdministrator(companyId);
			}
			gmNotifyRecords = generateGMNotifyRecord(userInfos, recordId, userId, content, SendType.EMAIL);
			break;
		default:

			content = String.format(AUDITOR_MSG, contact, phone);
			// 获取服务站长的信息
			userInfos = userTDao.getStationMasterByServiceStationId(serviceStationId);
			gmNotifyRecords = generateGMNotifyRecord(userInfos, recordId, userId, content, SendType.SMS);
			break;
		}
		String.format("获取GM申请单ID:%s的审核人 %s", recordId, userInfos);

		// 发送消息
		try {
			doPushMessageForGuidanz(gmNotifyRecords, userInfos);
		} catch (Exception e) {
			log.error("消息推送出现异常" + e.getMessage());
		}

		if(CollectionUtils.isNotEmpty(gmNotifyRecords)) {
			try {
				log.info("开始批量插入Guidanz消息推送记录");
				gMNotifyRecordDao.batchInsert(gmNotifyRecords);
			} catch (Exception e) {
				log.error("批量插入Guidanz消息推送记录异常 原因：" + e.getMessage());
			}
		}

	}


	/**
	 * 推送消息给用户
	 * USER_REJECT_MSG
	 */
	public void pushRejectMsgToUserForGuidanz(Long recordId, Long creator) {
		try {
			UserInfo userInfo = userTDao.getUserInfoByRecordId(recordId);
			if(userInfo != null) {
				List<UserInfo> userInfos = Arrays.asList(userInfo);
				// 生成消息推送记录
				List<GMNotifyRecordT> gmNotifyRecords = generateGMNotifyRecord(userInfos, recordId, creator, USER_REJECT_MSG, SendType.SMS);

				// 发送消息
				try {
					doPushMessageForGuidanz(gmNotifyRecords, userInfos);
				} catch (Exception e) {
					log.error("消息推送出现异常" + e.getMessage());
				}

				if(CollectionUtils.isNotEmpty(gmNotifyRecords)) {
					try {
						log.info("开始批量插入Guidanz消息推送记录");
						gMNotifyRecordDao.batchInsert(gmNotifyRecords);
					} catch (Exception e) {
						log.error("批量插入Guidanz消息推送记录异常 原因：" + e.getMessage());
					}
				}

			}
		} catch (Exception e) {
			log.error("推送失败消息给用户异常 原因：" + e.getMessage());
		}
	}







	/**
	 * 推送消息
	 * @param recordList
	 * @param userInfos
	 */
	private void doPushMessageForGuidanz(List<GMNotifyRecordT> recordList, List<UserInfo> userInfos) {
		if (CollectionUtils.isNotEmpty(recordList) && CollectionUtils.isNotEmpty(userInfos)) {
			// key:UserId  value:UserInfo
			Map<Long, UserInfo> userInfoMap = new HashMap<>();
			for (UserInfo userInfo : userInfos) {
				userInfoMap.put(userInfo.getUserId(), userInfo);
			}

			for (GMNotifyRecordT record : recordList) {
				UserInfo userInfo = userInfoMap.get(record.getReceiverId());
				if (!Objects.isNull(userInfo)) {
					switch (record.getSendType()) {
					// 短信推送
					case 1:
						String phone = userInfo.getPhone();
						if (StringUtils.isNotBlank(phone)) {
							String sendStatus = SmsUtils.sendMessage(phone, record.getMsgContent());
							if ("00".equals(sendStatus)) {
								record.setExceptionInfo(String.format("手机号:%s  发送成功", phone));
							} else {
								record.setExceptionInfo(String.format("状态码:%s  手机号:%s  发送失败", sendStatus, phone));
							}
						} else {
							record.setExceptionInfo("用户手机号为空");
						}
						break;
					// App推送
					case 2:
						String clientId = userInfo.getClientId();
						if (StringUtils.isNotBlank(clientId)) {
							boolean isSucc = NotifyUtil.push2Single(clientId, record.getMsgContent(), record.getMsgContent());
							if (isSucc) {
								record.setExceptionInfo(String.format("ClientId:%s   消息推送成功", clientId));
							} else {
								record.setExceptionInfo(String.format("ClientId:%s   消息推送失败", clientId));
							}
						} else {
							record.setExceptionInfo("ClientId为空");
						}
						break;
					// 邮箱推送
					case 3:
						String email = userInfo.getEmail();

						if (StringUtils.isNotEmpty(email)) {
							try {
								MailUtil.sendMail(email, "Guidanz审核提醒", record.getMsgContent());
								record.setExceptionInfo(email + "邮件已发送");
							} catch (Exception e) {
								log.error(email + "发送失败 原因：" + e.getMessage());
								record.setExceptionInfo("Email发送异常");
							}
						} else {
							record.setExceptionInfo("email为空");
						}

						break;
					default:
						record.setExceptionInfo("发送类型不支持");
						break;
					}

				} else {
					record.setExceptionInfo("用户不存在");
				}
			}
		}
	}


	private List<GMNotifyRecordT> generateGMNotifyRecord(List<UserInfo> userInfos, Long recordId, Long creator, String content, SendType...sendTypes) {
		if(CollectionUtils.isNotEmpty(userInfos)) {
			if(sendTypes != null && sendTypes.length > 0) {
				String realCurrentTime = LocalTimeUtil.getRealCurrentTime();

				List<GMNotifyRecordT> notifyRecords = new ArrayList<>();

				for (UserInfo userInfo : userInfos) {
					for (SendType sendType : sendTypes) {
						notifyRecords.add(doGenerateGMNotifyRecord(recordId, 1, userInfo.getUserId(), content, sendType.getSendType(), creator, realCurrentTime));
					}
				}

				return notifyRecords;
			}
		}
		return null;
	}



	private GMNotifyRecordT doGenerateGMNotifyRecord(Long recordId, Integer type, Long receiverId, String content, Integer sendType, Long creator, String currentTime) {
		GMNotifyRecordT notifyRecord = new GMNotifyRecordT();
		notifyRecord.setRecordId(recordId);
		notifyRecord.setType(type);
		notifyRecord.setSendTime(currentTime);
		notifyRecord.setReceiverId(receiverId);
		notifyRecord.setMsgContent(content);
		notifyRecord.setSendType(sendType);
		notifyRecord.setIsRead(0);
		notifyRecord.setCreator(creator);
		notifyRecord.setCreateTime(currentTime);
		return notifyRecord;
	}


	private enum SendType {
		SMS(1),
		APP(2),
		EMAIL(3);

		SendType(Integer sendType){
			this.sendType = sendType;
		}

		private Integer sendType;

		public Integer getSendType() {
			return sendType;
		}
	}

}
